/*
 * memory.c
 *
 *  Created on: 2016年8月7日
 *      Author: pengzhikang
 */

#include "memory.h"
#include "naskfunc.h"

/**
 * 内存检测函数
 * 检测从start地址到end地址范围内, 能够使用的内存的末尾地址
 */
unsigned int memtest(unsigned int start, unsigned int end) {
	char flg486 = 0;
	unsigned int eflg, cr0, i;
	//确认CPU是386还是486以上的
	eflg = io_load_eflags();
	eflg |= EFLAGS_AC_BIT; //AC-bit=1
	io_store_eflags(eflg);
	eflg = io_load_eflags();
	if ((eflg & EFLAGS_AC_BIT) != 0) {
		flg486 = 1;
	}
	eflg &= ~EFLAGS_AC_BIT; // AC-bit=0
	io_store_eflags(eflg);

	if (flg486 != 0) {
		cr0 = load_cr0();
		cr0 |= CR0_CACHE_DISABLE;
		store_cr0(cr0);
	}
	i = memtest_sub(start, end);

	if (flg486 != 0) {
		cr0 = load_cr0();
		cr0 &= ~CR0_CACHE_DISABLE;
		store_cr0(cr0);
	}
	return i;
}

/**
 * 内存管理结构初始化函数
 */
void memman_init(struct MEMMAN *man) {
	man->frees = 0;
	man->maxfrees = 0;
	man->lostsize = 0;
	man->losts = 0;
}

/**
 * 返回空闲内存大小的总和
 */
unsigned int memman_total(struct MEMMAN *man) {
	unsigned int i, t = 0;
	for (i = 0; i < man->frees; i++) {
		t += man->free[i].size;
	}
	return t;
}

/**
 * 内存分配函数
 */
unsigned int memman_alloc(struct MEMMAN *man, unsigned int size) {
	unsigned int i, a;
	for (i = 0; i < man->frees; i++) {
		if (man->free[i].size >= size) {
			a = man->free[i].address;
			man->free[i].address += size;
			man->free[i].size -= size;
			if (man->free[i].size == 0) {
				man->frees--;
				// 前移
				for (; i < man->frees; i++) {
					man->free[i] = man->free[i + 1];
				}
			}
			return a;
		}
	}
	return 0;
}

/**
 * 内存释放函数
 */
int memman_free(struct MEMMAN *man, unsigned int address, unsigned int size) {
	int i, j;
	for (i = 0; i < man->frees; i++) {
		if (man->free[i].address > address) {
			break;
		}
	}

	/*man->free[i - 1].address < address < man->free[i].address*/
	if (i > 0) {
		// 可与前面相连
		if (man->free[i - 1].address + man->free[i - 1].size == address) {
			man->free[i - 1].size += size;
			if (i < man->frees) {
				// 可与后面相连
				if (address + size == man->free[i].address) {
					man->free[i - 1].size += man->free[i].size;
					man->frees--;
					for (; i < man->frees; ++i) {
						man->free[i] = man->free[i + 1];
					}
				}
			}
			return 0;
		}
	}

	// 不可与前面的可用空间归纳到一起
	if (i < man->frees) {
		// 可与后面相连
		if (address + size == man->free[i].address) {
			man->free[i].address = address;
			man->free[i].size += size;
			return 0;
		}
	}

	// 不能与前面也不能和后面的空间归纳到一起
	if (man->frees < MEMMAN_FREES) {
		for (j = man->frees; j > i; j--) {
			man->free[j] = man->free[j - 1];
		}
		man->frees++;
		if (man->maxfrees < man->frees) {
			man->maxfrees = man->frees;
		}
		man->free[i].address = address;
		man->free[i].size = size;
		return 0;
	}
	man->losts++;
	man->lostsize += size;
	return -1;
}

/**
 * 申请4K内存
 */
unsigned int memman_alloc_4k(struct MEMMAN * man, unsigned int size) {
	unsigned int a;
	size = (size + 0xfff) & 0xfffff000; // 1.5 + 0.9 约等于 2
	a = memman_alloc(man, size);
	return a;
}

/**
 * 释放4K内存
 */
int memman_free_4k(struct MEMMAN * man, unsigned int address, unsigned int size) {
	int i;
	size = (size + 0xfff) & 0xfffff000;
	i = memman_free(man, address, size);
	return i;
}

